package com.example.smartwaterapi.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.smartwaterapi.entity.UserAchievement;
import com.example.smartwaterapi.mapper.UserAchievementMapper;
import com.example.smartwaterapi.service.UserAchievementService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * 用户成就服务实现类
 */
@Slf4j
@Service
public class UserAchievementServiceImpl extends ServiceImpl<UserAchievementMapper, UserAchievement> implements UserAchievementService {

    @Override
    @CacheEvict(value = "achievement", keyGenerator = "achievementCacheKeyGenerator")
    public boolean save(UserAchievement entity) {
        log.info("保存用户成就数据: {}", entity);
        try {
            if (entity.getCreatedAt() == null) {
                entity.setCreatedAt(LocalDateTime.now());
            }
            boolean result = super.save(entity);
            if (result) {
                log.info("用户成就数据保存成功, id: {}", entity.getId());
            } else {
                log.error("用户成就数据保存失败");
            }
            return result;
        } catch (Exception e) {
            log.error("保存用户成就数据异常", e);
            throw e;
        }
    }
    
    @Override
    @CacheEvict(value = "achievement", keyGenerator = "achievementCacheKeyGenerator")
    public boolean updateById(UserAchievement entity) {
        log.info("更新用户成就数据, id: {}", entity.getId());
        try {
            if (entity.getUpdatedAt() == null) {
                entity.setUpdatedAt(LocalDateTime.now());
            }
            boolean result = super.updateById(entity);
            if (result) {
                log.info("用户成就数据更新成功, id: {}", entity.getId());
            } else {
                log.warn("用户成就数据更新失败, id: {}, 可能记录不存在", entity.getId());
            }
            return result;
        } catch (Exception e) {
            log.error("更新用户成就数据异常, id: {}", entity.getId(), e);
            throw e;
        }
    }
    
    @Override
    @Cacheable(value = "achievement", key = "'id_' + #id", unless = "#result == null")
    public UserAchievement getById(Serializable id) {
        log.info("获取用户成就数据, id: {}", id);
        try {
            UserAchievement achievement = super.getById(id);
            if (achievement == null) {
                log.warn("未找到用户成就数据, id: {}", id);
            }
            return achievement;
        } catch (Exception e) {
            log.error("获取用户成就数据异常, id: {}", id, e);
            throw e;
        }
    }
    
    @Override
    @CacheEvict(value = "achievement", keyGenerator = "achievementCacheKeyGenerator")
    public boolean removeById(Serializable id) {
        log.info("删除用户成就数据, id: {}", id);
        try {
            boolean result = super.removeById(id);
            if (result) {
                log.info("用户成就数据删除成功, id: {}", id);
            } else {
                log.warn("用户成就数据删除失败, id: {}, 可能记录不存在", id);
            }
            return result;
        } catch (Exception e) {
            log.error("删除用户成就数据异常, id: {}", id, e);
            throw e;
        }
    }
    
    @Override
    @Cacheable(value = "achievement", key = "'user_' + #userId", unless = "#result == null || #result.isEmpty()")
    public List<UserAchievement> getUserAchievements(Long userId) {
        log.debug("获取用户成就列表, 用户ID: {}", userId);
        LambdaQueryWrapper<UserAchievement> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAchievement::getUserId, userId)
               .orderByDesc(UserAchievement::getCreatedAt);
        return list(wrapper);
    }
    
    @Override
    public Page<UserAchievement> getUserAchievementsPage(Long userId, Integer pageNum, Integer pageSize) {
        log.debug("分页获取用户成就列表, 用户ID: {}, 页码: {}, 每页数量: {}", userId, pageNum, pageSize);
        // 限制最大页大小，避免一次性查询过多数据导致内存压力
        pageSize = Math.min(pageSize, 50);
        
        Page<UserAchievement> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<UserAchievement> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserAchievement::getUserId, userId)
               .orderByDesc(UserAchievement::getCreatedAt);
        
        return page(page, wrapper);
    }
    
    @Override
    @Async("dataProcessExecutor")
    public CompletableFuture<List<UserAchievement>> checkUserAchievementsAsync(Long userId) {
        log.debug("异步检查用户成就, 用户ID: {}", userId);
        try {
            List<UserAchievement> newAchievements = new ArrayList<>();
            
            // 这里可以添加各种成就检查逻辑
            // 例如: 检查连续饮水天数、总饮水量等指标，达成则创建新成就
            
            // 批量保存新成就
            if (!newAchievements.isEmpty()) {
                saveBatch(newAchievements);
                log.info("异步检查用户成就完成, 用户ID: {}, 新增成就数量: {}", userId, newAchievements.size());
            }
            
            return CompletableFuture.completedFuture(newAchievements);
        } catch (Exception e) {
            log.error("异步检查用户成就异常, 用户ID: {}", userId, e);
            return CompletableFuture.completedFuture(new ArrayList<>());
        }
    }
    
    @Override
    public boolean batchProcessUserAchievements(List<Long> userIds) {
        log.debug("批量处理用户成就, 用户数量: {}", userIds.size());
        
        // 分批处理，每批最多20个用户
        final int BATCH_SIZE = 20;
        List<CompletableFuture<List<UserAchievement>>> futures = new ArrayList<>();
        
        for (int i = 0; i < userIds.size(); i += BATCH_SIZE) {
            int endIndex = Math.min(i + BATCH_SIZE, userIds.size());
            List<Long> batch = userIds.subList(i, endIndex);
            
            for (Long userId : batch) {
                futures.add(checkUserAchievementsAsync(userId));
            }
        }
        
        // 等待所有异步任务完成
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
        
        // 统计结果
        int totalNewAchievements = futures.stream()
                .map(CompletableFuture::join)
                .mapToInt(List::size)
                .sum();
        
        log.info("批量处理用户成就完成, 用户数量: {}, 新增成就总数: {}", 
                userIds.size(), totalNewAchievements);
        
        return true;
    }
} 